home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / vlapak1.zip / MODINFO.ZIP / DMAPLAY.ASM < prev    next >
Assembly Source File  |  1993-04-16  |  10KB  |  451 lines

  1.       DOSSEG
  2.       .MODEL SMALL
  3.       .STACK 200h
  4.       .CODE
  5.       .386
  6.       ASSUME CS:@CODE, DS:@CODE
  7.       Ideal
  8.  
  9. ────────────────────────────────────────────────────────
  10.  
  11. OldInt  dd  0       ;for the old DMA interrupt
  12.  
  13. BaseAddress dw  220h
  14. IrqNumber   db  7
  15. DMANumber   db  1
  16.  
  17. SampleSeg dw  0
  18. SampleOff dw  0
  19.  
  20. FileName  db  "jamhot.sam",0
  21. SamLength dw  ?
  22.  
  23. STRUC DMAInfo
  24.     Page    dw  ?,?
  25.     Length  dw  ?,?
  26.     Offset  dw  ?,?
  27.     Next    dw  0,0     ;changes 2nd one to a "2" if 2 buffers are needed
  28.     Current dw  0       ;0 or 1
  29. ENDS DMAInfo
  30.  
  31. DMA DMAInfo <>
  32.  
  33. ────────────────────────────────────────────────────────
  34.  
  35. ;==================
  36. ;==- Interrupts -==
  37. ;==================
  38.  
  39. PROC DMAINT FAR
  40.     pusha
  41.     cli
  42.  
  43.     mov     dx,[cs:BaseAddress]
  44.     add     dx,0eh   
  45.     in      al,dx               ;acknowledge interrupt
  46.  
  47.     xor     [cs:DMA.Current],1
  48.     mov     bx,[cs:DMA.Current]
  49.     add     bx,bx
  50.     mov     bx,[cs:bx + DMA.NEXT]
  51.     
  52.     mov     ax,[cs:bx + DMA.Page]
  53.     mov     ah,al
  54.     mov     cx,[cs:bx + DMA.Length]
  55.     mov     dx,[cs:bx + DMA.Offset]
  56.     call    TransferDma
  57.  
  58.     mov     al,20h
  59.     out     20h,al              ;end of hardware interrupt
  60.  
  61.     popa
  62.     sti
  63.     iret
  64. ENDP DMAINT
  65.  
  66. ;======================
  67. ;==- Start Transfer -==
  68. ;======================
  69.  
  70. PROC StartTransferDma NEAR
  71.     pusha
  72.  
  73.     mov     al,[cs:IrqNumber]
  74.     add     al,8
  75.     cbw
  76.     shl     al,2
  77.     mov     bx,ax
  78.     push    es
  79.     sub     ax,ax
  80.     mov     es,ax
  81.     mov     ax,[es:bx]
  82.     mov     [WORD LOW  cs:OldInt],ax           ; Grab the current interrupt
  83.     mov     ax,[es:bx+2]
  84.     mov     [WORD HIGH cs:OldInt],ax              ; so we can restore it later
  85.     pop     es
  86.  
  87.     mov     ax,[cs:DMA.Page]
  88.     mov     ah,al
  89.     mov     cx,[cs:DMA.Length]
  90.     mov     dx,[cs:DMA.Offset]
  91.     
  92.     mov     al,5
  93.     out     0ah,al          ;Mask off channel 1
  94.     xor     al,al
  95.     out     0ch,al          ;Clear byte pointer F/F to lowerbyte
  96.     mov     al,49h  
  97.     out     0bh,al          ;Set transfer mode to DAC (ADC = 45h)
  98.     mov     al,dl           ;LSB of BASE_ADDRESS
  99.     out     2,al
  100.     mov     al,dh           ;MSB of BASE_ADDRESS
  101.     out     2,al
  102.     mov     al,ah
  103.     out     83h,al          ;Page Number
  104.     mov     al,cl
  105.     out     3,al            ;LSB of DATA_Length
  106.     mov     al,ch
  107.     out     3,al            ;MSB of DATA_Length
  108.     mov     al,1
  109.     out     0ah,al          ;Enable Channel 1
  110.  
  111.     mov     ax,offset DMAInt
  112.     call    DoRealInt
  113.  
  114.     mov     al,14h          ;function 14h DMAmode 8-bit DAC
  115.     call    Sendcommand
  116.     mov     al,cl           ;send LSB of DATALENGTH
  117.     call    SendCommand
  118.     mov     al,ch           ;send MSB of DATALENGTH
  119.     call    SendCommand
  120.     
  121.     popa
  122.     ret
  123. ENDP StartTransferDma
  124.  
  125.     ;ah= page number
  126.     ;dx= BASE_ADDRESS
  127.     ;cx= DATA_LENGTH (-1)
  128. PROC TransferDma NEAR
  129.     pusha
  130.     mov     al,5
  131.     out     0ah,al          ;Mask off channel 1
  132.     xor     al,al
  133.     out     0ch,al          ;Clear byte pointer F/F to lowerbyte
  134.     mov     al,49h  
  135.     out     0bh,al          ;Set transfer mode to DAC (ADC = 45h)
  136.     mov     al,dl           ;LSB of BASE_ADDRESS
  137.     out     2,al
  138.     mov     al,dh           ;MSB of BASE_ADDRESS
  139.     out     2,al
  140.     mov     al,ah
  141.     out     83h,al          ;Page Number
  142.     mov     al,cl
  143.     out     3,al            ;LSB of DATA_Length
  144.     mov     al,ch
  145.     out     3,al            ;MSB of DATA_Length
  146.     mov     al,1
  147.     out     0ah,al          ;Enable Channel 1
  148.  
  149.     mov     al,14h          ;function 14h DMAmode 8-bit DAC
  150.     call    Sendcommand
  151.     mov     al,cl           ;send LSB of DATALENGTH
  152.     call    SendCommand
  153.     mov     al,ch           ;send MSB of DATALENGTH
  154.     call    SendCommand
  155.     popa
  156.     ret
  157. ENDP TransferDMA
  158.  
  159.     ;ah= TC (Time Constant = 256 - 1,000,000/HZ)
  160. PROC SetTimeConstant NEAR
  161.     mov     al,40h
  162.     call    SendCommand
  163.     mov     al,ah
  164.     call    SendCommand
  165.     ret
  166. ENDP SetTimeConstant
  167.  
  168. PROC TurnOffSpeaker NEAR
  169.     mov     al,0d3h         ;turn off speaker
  170.     call    Sendcommand
  171.     ret
  172. ENDP TurnOffSpeaker
  173.  
  174. PROC HaltDMA NEAR
  175.     mov     al,0d0h         ;Halt DMA
  176.     call    SendCommand
  177.     ret
  178. ENDP HaltDma
  179.  
  180.     ;al = command
  181. PROC SendCommand NEAR
  182.     push    dx
  183.     push    ax
  184.     mov     dx,[cs:BaseAddress]
  185.     add     dx,0ch
  186. @@Sendcommandloop:
  187.     in      al,dx
  188.     or      al,al
  189.     js      @@Sendcommandloop
  190.     pop     ax
  191.     out     dx,al
  192.     pop     dx
  193.     ret
  194. ENDP SendCommand
  195.  
  196. PROC TurnOnSpeaker NEAR
  197.     mov     al,0d1h
  198.     call    SendCommand
  199.     ret
  200. ENDP TurnOnSpeaker
  201.  
  202.     ;input- none 
  203.     ;output al=0 successful
  204.     ;       al=1 unsuccessful
  205.     ;DESTROYED: ax,dx,cx
  206.  
  207. PROC DspReset NEAR
  208.     mov     dx,[cs:baseaddress]
  209.     add     dx,06h
  210.     mov     al,1
  211.     out     dx,al
  212.     mov     cx,1000
  213.     push    di
  214.     rep     lodsb   ;wait for at least 3µS
  215.     pop     di
  216.     xor     al,al
  217.     out     dx,al
  218.  
  219.     add     dx,8         ;check WhichBuffer (22eh)
  220.     mov     cx,12000
  221. waitforstat:
  222.     in      al,dx
  223.     dec     cx
  224.     je      errorstat
  225.     test    al,10000000b
  226.     jz      waitforstat
  227.  
  228.     mov     cx,10000
  229.     sub     dx,4         ;(22ah)      
  230. waitforstat2:
  231.     in      al,dx
  232.     dec     cx
  233.     je      errorstat
  234.     cmp     al,0aah
  235.     jne     waitforstat2
  236.     mov     al,0
  237.     ret
  238. errorstat:
  239.     mov     al,1
  240.     ret
  241. ENDP DspReset
  242.  
  243. ;========================
  244. ;==- Start Interrupts -==
  245. ;========================
  246.  
  247.     ;cs:ax=location of interrupt
  248. PROC DoRealint NEAR
  249.     pushf                           ; Push flags
  250.     push    bx
  251.     push    cx
  252.     push    dx
  253.     cli                             ; Disable interrupts
  254.     mov     dx,ax
  255.     mov     al,[cs:IrqNumber]
  256.     add     al,8
  257.     cbw                             ; Convrt byte to word
  258.     shl     ax,2                    ; Shift w/zeros fill
  259.     mov     bx,ax
  260.     push    es
  261.     sub     ax,ax
  262.     mov     es,ax
  263.     mov     [es:bx],dx
  264.     mov     [es:bx+2],cs
  265.     pop     es
  266.     mov     cl,[cs:IrqNumber]
  267.     mov     ah,1
  268.     shl     ah,cl                   ; Shift w/zeros fill
  269.     not     ah
  270.     in      al,21h                  ; port 21h, 8259-1 int IMR
  271.     and     al,ah
  272.     out     21h,al                  ; port 21h, 8259-1 int comands
  273.     pop     dx
  274.     pop     cx
  275.     pop     bx
  276.     popf                            ; Pop flags
  277.     sti
  278.     ret
  279. ENDP DoRealint
  280.   
  281. PROC UnDoREALint NEAR
  282.     pushf
  283.     pusha
  284.     cli
  285.     mov     al,[cs:IrqNumber]
  286.     add     al,8
  287.     cbw
  288.     shl     ax,2
  289.     mov     di,ax
  290.     push    es
  291.     sub     ax,ax
  292.     mov     es,ax
  293.     mov     ax,[WORD LOW  cs:OldInt]              
  294.     mov     [es:di],ax
  295.     mov     ax,[WORD HIGH cs:OldInt]              
  296.     mov     [es:di+2],ax
  297.     pop     es
  298.     mov     cl,[cs:IrqNumber]               ; (=7)
  299.     mov     ah,1
  300.     shl     ah,cl                   ; Shift w/zeros fill
  301.     in      al,21h                  ; port 21h, 8259-1 int IMR
  302.     or      al,ah
  303.     out     21h,al                  ; port 21h, 8259-1 int comands
  304.     popa
  305.     popf                            ; Pop flags
  306.     sti
  307.     ret
  308. ENDP UnDoREALint
  309.  
  310.     ;Figgures the DMA buffer info
  311. PROC CalcForDMA NEAR
  312.     pushad
  313.     push    ds
  314.  
  315.     mov     ax,cs
  316.     mov     ds,ax
  317.     mov     es,ax
  318.  
  319.     mov     [2 + DMA.Next],0          ;assume we do only 1 buffer
  320.     
  321.     movzx   eax,[SampleSeg]
  322.     movzx   edx,[SampleOff]
  323.     call    MakePage
  324.     
  325.     cmp     cx,[SamLength]          ;is max less than needed?
  326.     jb      Skiplengthset           ;yes, must do 2 buffers
  327.  
  328.     mov     cx,[SamLength]
  329.     mov     [2 + DMA.NEXT],2
  330.     jmp     NoMore
  331.  
  332. Skiplengthset:
  333.     mov     bx,[SamLength]
  334.     sub     bx,cx
  335.     dec     bx
  336.     mov     [2 + DMA.Length],bx
  337.     mov     [2 + DMA.Offset],0
  338.     mov     [2 + DMA.Page],ax
  339.     inc     [2 + DMA.Page]
  340.  
  341. NoMore:
  342.     mov     [DMA.Page],ax
  343.     mov     [DMA.Offset],dx
  344.     dec     cx
  345.     mov     [DMA.Length],cx
  346.  
  347.     pop     ds
  348.     popad
  349.     ret
  350. ENDP CalcForDMA
  351.  
  352.     ;input: eax=segment
  353.     ;       edx=offset
  354.     ;output: ax=page
  355.     ;        dx=offset
  356.     ;        cx=MAX_LENGTH
  357. PROC MakePage NEAR 
  358.     shl     eax,4
  359.     add     edx,eax         ;edx = 32bit absolute address
  360.     
  361.     ror     edx,16
  362.     mov     al,dl           ;ax= page
  363.     xor     ah,ah
  364.     ror     edx,16
  365.  
  366.     mov     cx,dx
  367.     neg     cx
  368.     ret
  369. ENDP MakePage
  370.  
  371.   ; returns -1 if load not successful
  372. PROC  LoadSample NEAR
  373.     pusha
  374.     push    ds
  375.  
  376.     mov     ax,cs
  377.     mov     ds,ax
  378.     mov     dx,offset FileName
  379.     mov     ax,3D00h        ;open the file
  380.     int     21h
  381.     jc      @@Error
  382.  
  383.     mov     bx,ax
  384.     xor     dx,dx             ;load at offset 0
  385.     mov     cx,0ffffh         ;read in a whole segments worth
  386.     mov     ds,[cs:SampleSeg]
  387.     mov     ax,3F00h          ; Load in the sample
  388.     int     21h
  389.     mov     [cs:SamLength],ax
  390.  
  391.     mov     ax,3E00h          ;close the file
  392.     int     21h
  393.  
  394.     ;now fix the sam so it's playable on a SB
  395.     push    es
  396.     push    ds
  397.     pop     es
  398.  
  399.     mov     si,0
  400.     mov     di,0
  401.     mov     cx,[cs:SamLength]
  402.     cld
  403. FixItLoop:
  404.     lodsb
  405.     add     al,128
  406.     stosb
  407.     loop    FixItLoop
  408.  
  409.     pop     es
  410.     pop     ds
  411.     popa
  412.     xor     ax,ax
  413.     ret
  414.  
  415. @@Error:
  416.     pop     ds
  417.     popa
  418.     mov     ax,-1
  419.     ret
  420. ENDP  LoadSample
  421.  
  422. ────────────────────────────────────────────────────────────────────────────
  423.  
  424. START:
  425.     mov   bx,ss
  426.     add   bx,20h            ;put sample right after stack
  427.     mov   [cs:SampleSeg],bx
  428.  
  429.     call  LoadSample
  430.     call  CalcForDMA
  431.     call  DspReset
  432.  
  433.     mov   ah, 256- 1000000/8000  ; 256- 1000000/ HZ
  434.     call  SetTimeConstant
  435.  
  436.     call  TurnOnSpeaker
  437.     call  StartTransferDMA
  438.     
  439.     mov   ah,0
  440.     int   16h               ;wait for a keypress
  441.     
  442.     call  HaltDMA
  443.     call  UnDoRealInt
  444.     call  TurnOffSpeaker
  445.     call  DSPReset
  446.     
  447.     mov   ax,4c00h
  448.     int   21h
  449.  
  450. END START
  451.